package com.ruoyi.web.controller.inventory;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.InventoryOverviewDetailVO;
import com.ruoyi.system.domain.vo.InventoryOverviewVO;
import com.ruoyi.system.domain.vo.TotalValueDetailsVO;
import com.ruoyi.system.service.*;
import com.ruoyi.system.util.AbdulEmptyUtils;
import com.ruoyi.system.util.BaseResponse;
import com.ruoyi.system.util.StoreIdUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.DateUtils.parseDate;

@RestController
@RequestMapping("/inv_overview")
@Api(tags = "库存总览管理")
public class InventoryOverviewController {

    @Autowired
    private IProductInventoryService productInventoryService;

    @Autowired
    private StoreIdUtils storeIdUtils;

    @Autowired
    private IWarehousingEntryService warehousingEntryService;

    @Autowired
    private IInventoryDetailsService inventoryDetailsService;

    @Autowired
    private InvInventoryWorkOrderService workOrderService;

    @Autowired
    private IInvInventoryTransferService invInventoryTransferService;

    @Autowired
    private IReportingLossesService reportingLossesService;

    @Autowired
    private IStoreBusinessService storeBusinessService;

    @GetMapping("/detail")
    @ApiOperation("库存总览")
    public BaseResponse<InventoryOverviewVO> getDetail(Long warehouseId, Date startDate, Date endDate) {
        InventoryOverviewVO inventoryOverviewVO = new InventoryOverviewVO();
        List<ProductInventory> list = build(warehouseId, startDate, endDate);
        if (!AbdulEmptyUtils.isEmpty(list)) {
            Optional<BigDecimal> total = list.stream()
                    .map(ProductInventory::getTotalValue)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal::add);
            // 当前库存总值
            inventoryOverviewVO.setTotalInventory(total.orElse(new BigDecimal(0)));

            //高于上线物品
            long count = list.stream().filter(e -> e.getStockWarning().equals(2)).count();
            inventoryOverviewVO.setOverLimit(count);
            //低于下线物品
            long countUn = list.stream().filter(e -> e.getStockWarning().equals(1)).count();
            inventoryOverviewVO.setUnderLimit(countUn);
            long count1 = list.stream().filter(e -> e.getStockWarning().equals(0)).count();
            inventoryOverviewVO.setNormal(count1);
        }
        Map<String, Object> warehousing = warehousing(warehouseId, startDate, endDate);
        if (!AbdulEmptyUtils.isEmpty(warehousing)) {
            inventoryOverviewVO.setTotalIn((BigDecimal) warehousing.get("totalIn"));
            inventoryOverviewVO.setTotalOut((BigDecimal) warehousing.get("totalOut"));
        }
        LambdaQueryWrapper<InvInventoryWorkOrder> query = Wrappers.lambdaQuery();
        query.eq(!AbdulEmptyUtils.isEmpty(warehouseId), InvInventoryWorkOrder::getWarehouseId, warehouseId);
        query.between(InvInventoryWorkOrder::getCreateTime, startDate, endDate);
        query.eq(InvInventoryWorkOrder::getStoreId, storeIdUtils.getStoreId());
        List<InvInventoryWorkOrder> workOrderList = workOrderService.list(query);
        if (!AbdulEmptyUtils.isEmpty(workOrderList)) {
            long count = workOrderList.stream().filter(e -> e.getIsStatus().equals(1)).count();
            inventoryOverviewVO.setCheck(count);
        }
        LambdaQueryWrapper<InvInventoryTransfer> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(!AbdulEmptyUtils.isEmpty(warehouseId), InvInventoryTransfer::getOutWarehouse, warehouseId);
        lambdaQuery.between(InvInventoryTransfer::getCreateTime, startDate, endDate);
        lambdaQuery.eq(InvInventoryTransfer::getStoreId, storeIdUtils.getStoreId());
        List<InvInventoryTransfer> transferList = invInventoryTransferService.list(lambdaQuery);
        if (!AbdulEmptyUtils.isEmpty(transferList)) {
            long count = transferList.stream().filter(e -> e.getIsStatus().equals(1)).count();
            inventoryOverviewVO.setTransfer(count);
        }
        LambdaQueryWrapper<InvReportingLosses> query1 = Wrappers.lambdaQuery();
        query1.eq(!AbdulEmptyUtils.isEmpty(warehouseId), InvReportingLosses::getWarehouseId, warehouseId);
        query1.between(InvReportingLosses::getCreateTime, startDate, endDate);
        query1.eq(InvReportingLosses::getStoreId, storeIdUtils.getStoreId());
        List<InvReportingLosses> reportingLossesList = reportingLossesService.list(query1);
        if (!AbdulEmptyUtils.isEmpty(reportingLossesList)) {
            long count = reportingLossesList.stream().filter(e -> e.getIsStatus().equals(1)).count();
            inventoryOverviewVO.setLoss(count);
        }
        return BaseResponse.success(inventoryOverviewVO);
    }

    /**
     * 库存总览-收入总值详情
     *
     * @param warehouseId 仓库
     * @param startDate   开始时间
     * @param endDate     结束时间
     * @return
     */
    @ApiOperation("库存总览-收入总值详情")
    @GetMapping("/detail/in")
    public BaseResponse<InventoryOverviewDetailVO> getInDetail(Long warehouseId, Date startDate, Date endDate) {
//        Date startDate = parseDate("2025-06-25 00:00:00");
//        Date endDate = parseDate("2025-07-02 00:00:00");
        InventoryOverviewDetailVO inventoryOverviewDetailVO = new InventoryOverviewDetailVO();
        List<ProductInventory> list = build(warehouseId, startDate, endDate);
        if (!AbdulEmptyUtils.isEmpty(list)) {
            //库存商品总值
            Optional<BigDecimal> total = list.stream()
                    .map(ProductInventory::getTotalValue)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal::add);

            Optional<BigDecimal> goods = list.stream().filter(e -> e.getCategory().equals("商品")).map(ProductInventory::getTotalValue).reduce(BigDecimal::add);
            Optional<BigDecimal> accessories = list.stream().filter(e -> e.getCategory().equals("配品")).map(ProductInventory::getTotalValue).reduce(BigDecimal::add);
            Optional<BigDecimal> rawMaterial = list.stream().filter(e -> e.getCategory().equals("原料")).map(ProductInventory::getTotalValue).reduce(BigDecimal::add);

            BigDecimal totalInventory = total.orElse(BigDecimal.ZERO);
            BigDecimal goodsValue = goods.orElse(BigDecimal.ZERO);
            BigDecimal accessoriesValue = accessories.orElse(BigDecimal.ZERO);
            BigDecimal rawMaterialValue = rawMaterial.orElse(BigDecimal.ZERO);

            inventoryOverviewDetailVO.setInventory(goodsValue);
            inventoryOverviewDetailVO.setProductInventory(accessoriesValue);
            inventoryOverviewDetailVO.setRawMaterialInventory(rawMaterialValue);

            // 计算并设置百分比（保留两位小数）
            if (totalInventory.compareTo(BigDecimal.ZERO) > 0) {
                inventoryOverviewDetailVO.setInventoryPercent(
                        goodsValue.divide(totalInventory, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue());

                inventoryOverviewDetailVO.setProductInventoryPercent(
                        accessoriesValue.divide(totalInventory, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue());

                inventoryOverviewDetailVO.setRawMaterialInventoryPercent(
                        rawMaterialValue.divide(totalInventory, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue());
            } else {
                // 防止除以零的情况
                inventoryOverviewDetailVO.setInventoryPercent(0.0);
                inventoryOverviewDetailVO.setProductInventoryPercent(0.0);
                inventoryOverviewDetailVO.setRawMaterialInventoryPercent(0.0);
            }
        }
        Map<String, Object> warehousing = warehousing(warehouseId, startDate, endDate);
        if (!AbdulEmptyUtils.isEmpty(warehousing)) {
            List<TotalValueDetailsVO> inDetailList = new ArrayList<>(); //入库
            List<TotalValueDetailsVO> outDetailList = new ArrayList<>(); //出库

            BigDecimal totalIn = (BigDecimal) warehousing.get("totalIn"); //入库总值
            BigDecimal totalOut = (BigDecimal) warehousing.get("totalOut");//出库的总值
            Object warehousingList = warehousing.get("warehousingList");
            List<WarehousingEntry> warehousingArray = JSON.parseArray(warehousingList.toString(), WarehousingEntry.class);  //入库单
            Map<Long, List<WarehousingEntry>> warehousingMap = warehousingArray.stream()
                    .collect(Collectors.groupingBy(
                            WarehousingEntry::getStoreBusinessId,
                            Collectors.mapping(
                                    e -> e, // 提取每个对象
                                    Collectors.toList()  // 收集为 List<Long>
                            )
                    ));
            Set<Long> storeBusinessIdS = warehousingArray.stream().map(WarehousingEntry::getStoreBusinessId).collect(Collectors.toSet());
            LambdaQueryWrapper<StoreBusiness> wrapper = Wrappers.lambdaQuery();
            wrapper.in(StoreBusiness::getId, storeBusinessIdS);
            wrapper.in(StoreBusiness::getBusinessType, 1, 2);
            wrapper.eq(!AbdulEmptyUtils.isEmpty(warehouseId), StoreBusiness::getStoreId, warehouseId);
            List<StoreBusiness> storeBusinessList = storeBusinessService.list(wrapper);
            if (!AbdulEmptyUtils.isEmpty(storeBusinessList)) {
                Map<Long, List<StoreBusiness>> map = storeBusinessList.stream()
                        .collect(Collectors.groupingBy(
                                StoreBusiness::getId,
                                Collectors.mapping(e -> e,
                                        Collectors.toList()))
                        );

                for (Long storeBusinessId : warehousingMap.keySet()) {
                    List<WarehousingEntry> warehousingEntries = warehousingMap.get(storeBusinessId);
                    TotalValueDetailsVO totalValueDetailsVO = new TotalValueDetailsVO();
                    List<StoreBusiness> storeBusinesses = map.get(storeBusinessId);
                    totalValueDetailsVO.setType(storeBusinesses.get(0).getName());
                    LambdaQueryWrapper<InventoryDetails> lwq = Wrappers.lambdaQuery();
                    lwq.in(InventoryDetails::getWarehousingEntryId, warehousingEntries.stream().map(WarehousingEntry::getId).collect(Collectors.toList()));
                    List<InventoryDetails> inventoryDetailsList = inventoryDetailsService.list(lwq);
                    Optional<BigDecimal> reduce = inventoryDetailsList.stream().map(InventoryDetails::getInventoryValue).filter(Objects::nonNull).reduce(BigDecimal::add);
                    if (!AbdulEmptyUtils.isEmpty(storeBusinesses) && storeBusinesses.get(0).getBusinessType().equals(1)) {
                        //入库
                        totalValueDetailsVO.setAmount(reduce.orElse(BigDecimal.ZERO));
                        totalValueDetailsVO.setPercent(totalValueDetailsVO.getAmount().divide(totalIn, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue());
                        inDetailList.add(totalValueDetailsVO);
                    } else if (!AbdulEmptyUtils.isEmpty(storeBusinesses) && storeBusinesses.get(0).getBusinessType().equals(2)) {
                        totalValueDetailsVO.setAmount(reduce.orElse(BigDecimal.ZERO));
                        totalValueDetailsVO.setPercent(totalValueDetailsVO.getAmount().divide(totalOut, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue());
                        outDetailList.add(totalValueDetailsVO);
                    }
                }
            }
            inventoryOverviewDetailVO.setTotalInDetails(inDetailList);
            inventoryOverviewDetailVO.setTotalOutDetails(outDetailList);
        }
        return BaseResponse.success(inventoryOverviewDetailVO);
    }

    /**
     * 抽离公共逻辑
     */
    public List<ProductInventory> build(Long warehouseId, Date startDate, Date endDate) {
        if (AbdulEmptyUtils.isEmpty(startDate) || AbdulEmptyUtils.isEmpty(endDate)) {
            throw new RuntimeException("开始时间和结束时间不能为空");
        }
        LambdaQueryWrapper<ProductInventory> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(!AbdulEmptyUtils.isEmpty(warehouseId), ProductInventory::getWarehouseId, warehouseId);
        wrapper.between(ProductInventory::getCreateTime, startDate, endDate);
        wrapper.eq(ProductInventory::getStoreId, storeIdUtils.getStoreId());
        return productInventoryService.list(wrapper);
    }


    public Map<String, Object> warehousing(Long warehouseId, Date startDate, Date endDate) {
        Map<String, Object> hashMap = new HashMap<>();
        LambdaQueryWrapper<WarehousingEntry> lqw = Wrappers.lambdaQuery();
        lqw.eq(!AbdulEmptyUtils.isEmpty(warehouseId), WarehousingEntry::getWarehouseId, warehouseId);
        lqw.between(WarehousingEntry::getCreateTime, startDate, endDate);
        lqw.eq(WarehousingEntry::getStoreId, storeIdUtils.getStoreId());
        List<WarehousingEntry> warehousingList = warehousingEntryService.list(lqw); //入库单

        if (!AbdulEmptyUtils.isEmpty(warehousingList)) {
            LambdaQueryWrapper<InventoryDetails> detailLqw = Wrappers.lambdaQuery(); //查询出入库明细
            detailLqw.in(InventoryDetails::getWarehousingEntryId, warehousingList.stream().map(WarehousingEntry::getId).collect(Collectors.toSet()));
            List<InventoryDetails> inventoryDetailsList = inventoryDetailsService.list(detailLqw);
            if (!AbdulEmptyUtils.isEmpty(inventoryDetailsList)) {
                Optional<BigDecimal> reduce = inventoryDetailsList.stream()
                        .filter(e -> e.getIsType().equals(1))
                        .map(InventoryDetails::getInventoryValue)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal::add);
                //入库总值
                hashMap.put("totalIn", reduce.orElse(new BigDecimal(0)));

                Optional<BigDecimal> reduce1 = inventoryDetailsList.stream()
                        .filter(e -> e.getIsType().equals(2))
                        .map(InventoryDetails::getInventoryValue)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal::add);
                //出库总值
                hashMap.put("totalOut", reduce1.orElse(new BigDecimal(0)));
                hashMap.put("warehousingList", JSON.toJSONString(warehousingList)); //入库单
            }
        }
        return hashMap;
    }
}
